Two level quantization support - #76
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
x+y quantization Phase 1: split a code into a base filter layer and an ex refine layer
Adds the quantization primitives for x+y — one code of
base_bits + ex_bits, stored once and split across two regions. The topbase_bitsform a cheap-to-scan filter layer with their own factors; the bottomex_bitsform the refine layer carrying the combined code's factors. The base bits are never stored twice: the refine step recovers the combined inner product from the filter step's viaip(base) · 2^ex_bits + ip(ex).This generalises the existing 1+y split, where the base layer is always the single sign bit.
What's here
data_layout.hppBaseDataMap/ConstBaseDataMap— base code plus its three factorsrabitq_impl.hppxy_bits:code_factors,split_code_with_factor,validate_bit_size;total_bits::combined_coderabitq.hppquantize_xy_singleestimator.hppxy_single_base_dist(filter),xy_single_full_dist(one-shot both layers)query.hppSplitSingleQuerytakesbase_bits, defaulting to 1Nothing is wired to a consumer yet — no batch variant, no IVF or HNSW path.
This is the primitive layer only.
Backward compatibility
SplitSingleQuery's newbase_bitsparameter is trailing and defaults to 1, so every existing call site is untouched. Atbase_bits == 1,kbxsumq()computes−(2^(1+ex_bits)−1)/2, bit-for-bit what it computed before.Refactors to existing code
total_bits::combined_codefactors out the sign-bit-over-magnitude construction thatrabitq_scalar_implandrabitq_full_implboth assembled inline;rabitq_scalar_implnow delegates to it, dropping adim-sized buffer and a pass.rabitq_full_implcan't yet —ex_bits_code_with_factorproduces the magnitude and the factors together.Next Phase
Issues
Verification
Clean build, 41 tests,
check-formatandcheck-tidyall clean. Beyond the suite:combined_codewas checked against the scalar loop it replaces over 46,080 comparisons spanningtotal_bits1–9 with exact zeros seeded. No mismatches, every code inside[0, 2^total_bits).METRIC_IP is untested —
code_factorshas two metric branches and only L2 is exercised.